package com.wty.swhn.wty;

import android.app.Activity;
import android.app.Application;
import android.content.Intent;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.provider.Settings;
import android.telephony.gsm.SmsMessage.MessageClass;
import android.util.Log;
import android.widget.Toast;

import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
import org.jivesoftware.smack.PacketInterceptor;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.Roster.SubscriptionMode;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.RosterPacket;
import org.jivesoftware.smack.packet.Presence.Type;
import org.jivesoftware.smack.provider.PrivacyProvider;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smackx.GroupChatInvitation;
import org.jivesoftware.smackx.PrivateDataManager;
import org.jivesoftware.smackx.packet.ChatStateExtension;
import org.jivesoftware.smackx.packet.LastActivity;
import org.jivesoftware.smackx.packet.OfflineMessageInfo;
import org.jivesoftware.smackx.packet.OfflineMessageRequest;
import org.jivesoftware.smackx.packet.SharedGroupsInfo;
import org.jivesoftware.smackx.provider.AdHocCommandDataProvider;
import org.jivesoftware.smackx.provider.BytestreamsProvider;
import org.jivesoftware.smackx.provider.DataFormProvider;
import org.jivesoftware.smackx.provider.DelayInformationProvider;
import org.jivesoftware.smackx.provider.DiscoverInfoProvider;
import org.jivesoftware.smackx.provider.DiscoverItemsProvider;
import org.jivesoftware.smackx.provider.MUCAdminProvider;
import org.jivesoftware.smackx.provider.MUCOwnerProvider;
import org.jivesoftware.smackx.provider.MUCUserProvider;
import org.jivesoftware.smackx.provider.MessageEventProvider;
import org.jivesoftware.smackx.provider.MultipleAddressesProvider;
import org.jivesoftware.smackx.provider.RosterExchangeProvider;
import org.jivesoftware.smackx.provider.StreamInitiationProvider;
import org.jivesoftware.smackx.provider.VCardProvider;
import org.jivesoftware.smackx.provider.XHTMLExtensionProvider;
import org.jivesoftware.smackx.search.UserSearch;
import org.xmlpull.v1.XmlPullParserException;

import com.wty.swhn.wty.model.PrivateChatEntity;
import com.wty.swhn.wty.util.Const;
import com.wty.swhn.wty.util.L;
import com.wty.swhn.wty.util.PreferencesUtils;
import com.wty.swhn.wty.util.Tools;
import com.wty.swhn.wty.view.AddFriendActivity;
import com.wty.swhn.wty.view.AddFriendchileActivity;
import com.wty.swhn.wty.view.Receiver;
import com.wty.swhn.wty.view.TopickActivity;
import com.wty.swhn.wty.view.fragment.MyFriendFragment;

import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;

/**
 * Created by swhn on 2016/8/5.
 */
public class TApplication extends Application {
	public static XMPPConnection xmppConnection;
	public static String currentUser;// 本客户端userjid。
	public static String host, serviceName;// 主机与服务器名称
	public static int port;// 端口号
	public static long appStartTime;// 开始时间
	public static boolean isConnected = false;
	public static final String STA = "TApplication";
	public static TApplication instance;// application系统组件保存系统信息
	// -1:没网 1:mobile,2:wifi
	public static int networkState = Const.NET_STATE_WIFI;
	// 我的消息，放的消息有添加好友，聊天的，系统，一定要做成publc static
	public static ArrayList<Object> listMyMessage = new ArrayList<Object>();
	// 存放Activity
	public static ArrayList<Activity> listActivity = new ArrayList<Activity>();
	// 存放添加好友消息
	public static ArrayList<Object> msgs = new ArrayList<Object>();
	private final static String TAG = "TApplication";
	private Intent intent;

	@Override
	public ClassLoader getClassLoader() {
		return super.getClassLoader();
	}

	// 用真机测试
	// 在真机上测试网通不通
	// 真机连124.207.192.18,连上，连你自己的笔记本，台式机，要测一下网络通不通
	// 在真机上打开浏览器，访问 http://ip:9090

	@Override
	public void onCreate() {
		super.onCreate();
		instance = this;
		L.isDebug = 	PreferencesUtils.getPrefBoolean(TApplication.this, Const.ISNEEDLOG, true);
		Log.i("LoginBiz",
				"onCreate threadId" + Thread.currentThread().getId() + "," + Thread.currentThread().getName());
		appStartTime = System.currentTimeMillis();
		try {
			readConfig();
			getConnection();

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public XMPPConnection getConnection() {
		if (xmppConnection == null) {
			openConnection();
		}
		return xmppConnection;

	}

	// 联网
	public void openConnection() {
		try {
			if (null == xmppConnection || !xmppConnection.isAuthenticated()) {
				XMPPConnection.DEBUG_ENABLED = true;// 开启DEBUG模式
				// 配置连接
				ConnectionConfiguration config = new ConnectionConfiguration(host, port, serviceName);
				config.setReconnectionAllowed(true);
				config.setSendPresence(true);
				config.setSASLAuthenticationEnabled(true);
				config.setSecurityMode(SecurityMode.disabled); // asmack用证书进行加密
				xmppConnection = new XMPPConnection(config);
				// 收到好友邀请后manual表示需要经过同意,accept_all表示不经同意自动为好友
				Roster.setDefaultSubscriptionMode(Roster.SubscriptionMode.manual);// manual：
				XMPPConnection connection = new XMPPConnection(config);
				// 配置各种Provider，如果不配置，则会无法解析数据
				configureConnection(ProviderManager.getInstance());
			}
			registerIntercepterListener();
			new Thread("connectChatServer") {
				@Override
				public void run() {

					try {
						// 当loginBiz，要用xmppConnection的时候，
						// xmppConnection = new XMPPConnection(config);没执行到。
						// ConnectionConfiguration config = new
						// ConnectionConfiguration(
						// host, port, serviceName);
						// xmppConnection = new XMPPConnection(config);
						long startTime = System.currentTimeMillis();
						xmppConnection.connect();
						long endTime = System.currentTimeMillis();
						Log.i("LoginBiz", "connectChat  threadId=" + Thread.currentThread().getId() + ","
								+ Thread.currentThread().getName() + "time=" + (endTime - startTime));
						isConnected = xmppConnection.isConnected();
						Log.i(STA, "联接结果==" + isConnected);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}.start();

		} catch (Exception xe) {
			xe.printStackTrace();
		}
	}

	/**
	 * 读取res/xml/config.xml
	 */
	private void readConfig() {
		try {
			// 需要应用程序资源，如应用工程中assets和res目录下的图片，layout，values等，或者需要系统内置的资源。
			// 我们获取这些资源的入口对象都是Resources对象，并博文将分析如何获取Resources对象。
			// 在一个Acitvity或者一个Service中，我们直接this.getResources()方法，就可以获得Reousrces对象。
			// 其实Acitivity或者Service本质上就是一个Context，getResources()方法来自Context，
			// 而真正实现Context接口是ContextImpl类，所以调用的实际上时ContextImpl类的getResources()方法。
			Resources resources = getResources();
			// Android用XmlResourceParser读取XML资源
			XmlResourceParser parser = resources.getXml(R.xml.config);

			// getType
			int eventType = parser.getEventType();
			String tagName;
			while (eventType != XmlResourceParser.END_DOCUMENT) {
				/*
				 * <config> <!-- 124.207.192.18 --> <host>124.207.192.18</host>
				 * <port>5222</port> <serviceName>tarena.com</serviceName>
				 * </config>
				 */
				switch (eventType) {
				case XmlResourceParser.START_TAG:
					tagName = parser.getName();// <host>
					if ("host".equals(tagName)) {
						host = parser.nextText();// <host>的下个文本就是“124.207.192.18”

					}
					if ("port".equals(tagName)) {
						port = Integer.parseInt(parser.nextText());
					}
					if ("serviceName".equals(tagName)) {
						serviceName = parser.nextText();
					}
					break;
				}
				eventType = parser.next();// 下一个<host>是<port>
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (XmlPullParserException e) {
			e.printStackTrace();
		}

	}

	/**
	 * xmpp配置
	 */
	private void configureConnection(ProviderManager pm) {
		// Private Data Storage
		pm.addIQProvider("query", "jabber:iq:private", new PrivateDataManager.PrivateDataIQProvider());
		// Time
		try {
			pm.addIQProvider("query", "jabber:iq:time", Class.forName("org.jivesoftware.smackx.packet.Time"));
		} catch (Exception e) {
			e.printStackTrace();
		}
		// Roster Exchange
		pm.addExtensionProvider("x", "jabber:x:roster", new RosterExchangeProvider());
		// Message Events
		pm.addExtensionProvider("x", "jabber:x:event", new MessageEventProvider());
		// Chat State
		pm.addExtensionProvider("active", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
		pm.addExtensionProvider("composing", "http://jabber.org/protocol/chatstates",
				new ChatStateExtension.Provider());
		pm.addExtensionProvider("paused", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
		pm.addExtensionProvider("inactive", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
		pm.addExtensionProvider("gone", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
		// XHTML
		pm.addExtensionProvider("html", "http://jabber.org/protocol/xhtml-im", new XHTMLExtensionProvider());
		// Group Chat Invitations
		pm.addExtensionProvider("x", "jabber:x:conference", new GroupChatInvitation.Provider());
		// Service Discovery # Items //解析房间列表
		pm.addIQProvider("query", "http://jabber.org/protocol/disco#items", new DiscoverItemsProvider());
		// Service Discovery # Info //某一个房间的信息
		pm.addIQProvider("query", "http://jabber.org/protocol/disco#info", new DiscoverInfoProvider());
		// Data Forms
		pm.addExtensionProvider("x", "jabber:x:data", new DataFormProvider());
		// MUC User
		pm.addExtensionProvider("x", "http://jabber.org/protocol/muc#user", new MUCUserProvider());
		// MUC Admin
		pm.addIQProvider("query", "http://jabber.org/protocol/muc#admin", new MUCAdminProvider());
		// MUC Owner
		pm.addIQProvider("query", "http://jabber.org/protocol/muc#owner", new MUCOwnerProvider());
		// Delayed Delivery
		pm.addExtensionProvider("x", "jabber:x:delay", new DelayInformationProvider());
		// Version
		try {
			pm.addIQProvider("query", "jabber:iq:version", Class.forName("org.jivesoftware.smackx.packet.Version"));
		} catch (ClassNotFoundException e) {
			// Not sure what's happening here.
		}
		// VCard
		pm.addIQProvider("vCard", "vcard-temp", new VCardProvider());
		// Offline Message Requests
		pm.addIQProvider("offline", "http://jabber.org/protocol/offline", new OfflineMessageRequest.Provider());
		// Offline Message Indicator
		pm.addExtensionProvider("offline", "http://jabber.org/protocol/offline", new OfflineMessageInfo.Provider());
		// Last Activity
		pm.addIQProvider("query", "jabber:iq:last", new LastActivity.Provider());
		// User Search
		pm.addIQProvider("query", "jabber:iq:search", new UserSearch.Provider());
		// SharedGroupsInfo
		pm.addIQProvider("sharedgroup", "http://www.jivesoftware.org/protocol/sharedgroup",
				new SharedGroupsInfo.Provider());
		// JEP-33: Extended Stanza Addressing
		pm.addExtensionProvider("addresses", "http://jabber.org/protocol/address", new MultipleAddressesProvider());
		pm.addIQProvider("si", "http://jabber.org/protocol/si", new StreamInitiationProvider());
		pm.addIQProvider("query", "http://jabber.org/protocol/bytestreams", new BytestreamsProvider());
		pm.addIQProvider("query", "jabber:iq:privacy", new PrivacyProvider());
		pm.addIQProvider("command", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider());
		pm.addExtensionProvider("malformed-action", "http://jabber.org/protocol/commands",
				new AdHocCommandDataProvider.MalformedActionError());
		pm.addExtensionProvider("bad-locale", "http://jabber.org/protocol/commands",
				new AdHocCommandDataProvider.BadLocaleError());
		pm.addExtensionProvider("bad-payload", "http://jabber.org/protocol/commands",
				new AdHocCommandDataProvider.BadPayloadError());
		pm.addExtensionProvider("bad-sessionid", "http://jabber.org/protocol/commands",
				new AdHocCommandDataProvider.BadSessionIDError());
		pm.addExtensionProvider("session-expired", "http://jabber.org/protocol/commands",
				new AdHocCommandDataProvider.SessionExpiredError());
	}

	/**
	 * 让asmack框架中的interface packetInterceptor,PakcetListener指向我们写的实现类
	 */
	private void registerIntercepterListener() {
		AllPacketInterceptor allPacketInterceptor = new AllPacketInterceptor();
		xmppConnection.addPacketInterceptor(allPacketInterceptor, null);
		ALLPacketListener allPacketListener = new ALLPacketListener();
		xmppConnection.addPacketListener(allPacketListener, null);
		privateChatFiler chatFiler=new privateChatFiler();
 		PrivateChatListener privateChatListener=new PrivateChatListener();
		xmppConnection.addPacketListener(privateChatListener, chatFiler);
	}

	class AllPacketInterceptor implements PacketInterceptor {

		@Override
		public void interceptPacket(Packet packet) {
			Log.i("AllPacketIntercepto", "===============" + packet.toXML());
		}
	}

	
	class privateChatFiler implements PacketFilter{

		@Override
		public boolean accept(Packet packet) {
		
			if(packet instanceof Message){
				
				Message message=(Message) packet;
				Message.Type type=message.getType();
				if(type==Message.Type.chat){
					return true;
				}
			}
			return false;
		}
		
	}
	// 服务器返回,接口得到服务器返回的信息
	class ALLPacketListener implements PacketListener {

		@Override
		public void processPacket(Packet packet) {
			Log.i("AllPacketListener", "class info:" + packet.toString() + "xml: " + packet.toXML());
			// <presence>
			// 标签名对应一个类
			// Presence-->Presence
			if (packet instanceof org.jivesoftware.smack.packet.Presence) {
				Presence presence = (Presence) packet;
				Type type = presence.getType();
				String gN = (String) presence.getProperty("groupName");
 				String nN = (String) presence.getProperty("nickName");
  				String fromuser = (String) presence.getProperty("fromuser");
				String cgl = (String) presence.getProperty("cgl");
				String over = (String) presence.getProperty("over");
				String ok = (String) presence.getProperty("ok");

				Log.e("allpacketListener",
						"type==" + type + "=gr=" + "@=" + "gN" + gN + "@=" + "nN" + nN + "==fromuser==" + fromuser);
				String from = presence.getFrom();
				String to = presence.getTo();
				Log.e(TAG, "fromNane==" + from + "==toName=" + to);
				if (type == Type.unsubscribe) {// 他取消订阅别人，请求删除某好友
					getBroadCase(Const.ADD_ADDFRIEND_DEL_CONSENT, from, null, null, null, null, null);
					Log.i("AllPacketListener", from + "删除好友");
				}
				if (type == Type.subscribed) {// 统一被别人订阅，也就是确认被对方加为好友
					Log.i("AllPacketListener", from + "同意======");

					getBroadCase(Const.ADD_ADDFRIEND_CONSENT, from, gN, nN, to, fromuser, null);
					Log.i("AllPacketListener", from + "同意======---------");

				}
				if (type == Type.subscribe) {// 请求订阅别人,请求加对方为好友
					// && "over".equals(over)
					if ("true".equals(fromuser)) {
						Log.i("AllPacketListener", from + "请求加为好友++======");
						getBroadCase(Const.REQUESE_ADDFRIEND_OK, from, gN, nN, to, fromuser, over);
						Log.i("AllPacketListener", from + "请求为好友++===fromuser=====" + fromuser);

					}

				}

				if (type == Type.unsubscribed) {// 拒绝被别人订阅，即拒绝对方的添加请求
					getBroadCase(Const.REFUSE_ADDFRIEND, from, null, null, null, null, null);
					Log.i("AllPacketListener", from + "拒绝添加好友++======----------");
				}
			}
 			if (packet instanceof RosterPacket) {
				// 说明服务器推送过来的信息是好友信息
				// 发广播，更新expandableListView
				getBroadCase(Const.ACTION_UPDATE_FRIEND, null, null, null, null, null, null);
			}
			// <message>
 			return;
		}
	}

	//好友消息（文本）监听器
	class PrivateChatListener implements PacketListener {

		@Override
		public void processPacket(Packet packet) {
			Log.e(TAG, "privateChatListener-packet=" + packet);
			try {
				
 				Message message = (Message) packet; 
				String fromName = message.getFrom();//未处理fromName=tlbb@swhn-pc/Spark 2.6.3;
				Log.e(TAG, "from=" + fromName);
 				if (fromName.contains("/")) {
 					fromName = fromName.substring(0, fromName.indexOf("/"));
 					PrivateChatEntity.addMessage(fromName, message);
 					Intent intent = new Intent(Const.ACTION_SHOW_PRIVATE_MESSAGE);
					intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);// 默认的跳转类型,它会重新创建一个新的Activity，不过与这种情况，比如说Task1中有A,B,C三个Activity,此时在C中启动D的话，如果在AndroidManifest.xml文件中给D添加了Affinity的值和Task中的不一样的话，则会在新标记的Affinity所存在的Task中压入这个Activity。如果是默认的或者指定的Affinity和Task一样的话，就和标准模式一样了启动一个新的Activity.
					sendBroadcast(intent);
				}
			} catch (Exception e) {
				// TODO: handle exception
			}
		}

	}

	// 广播
	void getBroadCase(String cons, String from, String gN, String nN, String to, String fromuser, String over) {
		intent = new Intent(cons);
		intent.putExtra("from", from);
		intent.putExtra("nN", nN);
		intent.putExtra("gN", gN);
		intent.putExtra("to", to);
		intent.putExtra("fromuser", fromuser);
		intent.putExtra("over", over);
		sendBroadcast(intent);
	}

	// 用真机测试
	// 在真机上测试网通不通
	// 真机连124.207.192.18,连上，连你自己的笔记本，台式机，要测一下网络通不通
	// 在真机上打开浏览器，访问 http://ip:9090
	public void exit() {
		for (Activity activity : listActivity) {
			activity.finish();
		}

		// 2.断开连接
		// 3,关闭整个应用程序(activity,service,receiver,appliation)
		// 手机上运行多个apk,每个apk是一个虚拟机
		// 关闭这个apk的虚拟机，Application就没有了，
		// 从程序列表中再次启动，执行Applicatio.onCrate()
		xmppConnection.disconnect();

		// 3,关闭整个应用程序(activity,service,receiver,appliation)
		// 手机上运行多个apk,每个apk是一个虚拟机
		// 关闭这个apk的虚拟机，Application就没有了，
		// 从程序列表中再次启动，执行Applicatio.onCrate()
		System.exit(0);
	}

}
